package com.zensun.system.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zensun.common.annotation.DataScope;
import com.zensun.common.utils.Assert;
import com.zensun.system.domain.SysDept;
import com.zensun.system.domain.SysUser;
import com.zensun.system.domain.dto.SysDeptDto;
import com.zensun.system.domain.dto.SysDeptExcludeDto;
import com.zensun.system.domain.vo.SysDeptDetailVo;
import com.zensun.system.domain.vo.SysDeptTreeListVo;
import com.zensun.system.domain.vo.SysDeptTreeVo;
import com.zensun.system.mapper.SysDeptMapper;
import com.zensun.system.mapper.SysUserMapper;
import com.zensun.system.service.ISysDeptService;
import com.zensun.system.util.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 部门管理 服务实现
 *
 * @author gmk
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysUserMapper userMapper;

    /**
     * 查询部门列表树
     *
     * @param sysDeptDto
     * @return
     */
    @DataScope(deptAlias = "d")
    @Override
    public List<SysDeptTreeListVo> selectDepTreeList(SysDeptDto sysDeptDto) {
        List<SysDeptTreeListVo> sysDeptVos = CollStreamUtil.toList(deptMapper.selectDeptList(sysDeptDto), sysDept -> {
            SysDeptTreeListVo sysDeptTreeListVo = new SysDeptTreeListVo();
            BeanUtils.copyProperties(sysDept, sysDeptTreeListVo);
            sysDeptTreeListVo.setIsSelf(SecurityUtils.getDeptId().equals(sysDeptTreeListVo.getDeptId()));
            return sysDeptTreeListVo;
        });
        Long topId = sysDeptVos.stream().map(SysDeptTreeListVo::getParentId).min(Long::compareTo).get();
        return buildDeptListTree(sysDeptVos, topId);
    }

    /**
     * 部门树
     *
     * @param deptVoList
     * @return
     */
    private List<SysDeptTreeListVo> buildDeptListTree(List<SysDeptTreeListVo> deptVoList, Long topId) {
        List<SysDeptTreeListVo> deptList = deptVoList.stream().filter((deptVo) -> {
            //查询一级数据
            return deptVo.getParentId().equals(topId);
        }).map((deptVo) -> {
            //构造一级数据的children
            deptVo.setChildren(getChildrens(deptVo, deptVoList));
            return deptVo;
        }).collect(Collectors.toList());
        return deptList;
    }

    public List<SysDeptTreeListVo> getChildrens(SysDeptTreeListVo root, List<SysDeptTreeListVo> deptList) {
        List<SysDeptTreeListVo> collect = deptList.stream().filter((deptVo) -> {
            return deptVo.getParentId().equals(root.getDeptId());
        }).map((deptVo) -> {
            deptVo.setChildren(getChildrens(deptVo, deptList));
            return deptVo;
        }).collect(Collectors.toList());

        return collect;
    }

    /**
     * 查询部门树下拉框
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<SysDeptTreeVo> excludeChild(SysDeptExcludeDto sysDeptExcludeDto) {
        //1.查询部门的所有数据
        SysDeptDto sysDeptDto = new SysDeptDto();
        sysDeptDto.setParams(sysDeptExcludeDto.getParams());
        List<SysDept> sysDepts = deptMapper.selectDeptList(sysDeptDto);


        //构造返回的数据
        List<SysDeptTreeListVo> depts = new ArrayList<>();
        Long addId = -1L;
        if (addId.equals(sysDeptExcludeDto.getDeptId())) {
            //全量的数据
            depts = CollStreamUtil.toList(sysDepts, sysDept -> {
                SysDeptTreeListVo sysDeptTreeListVo = new SysDeptTreeListVo();
                BeanUtils.copyProperties(sysDept, sysDeptTreeListVo);
                return sysDeptTreeListVo;
            });
        } else {
            //去除本部门或者包含本部门的子部门
            depts = sysDepts.stream()
                    .filter(sysDept -> !sysDept.getDeptId().equals(sysDeptExcludeDto.getDeptId()) && !ArrayUtil.contains(StrUtil.split(sysDept.getAncestors(), ","), String.valueOf(sysDeptExcludeDto.getDeptId())))
                    .map(sysDept -> {
                        SysDeptTreeListVo sysDeptTreeListVo = new SysDeptTreeListVo();
                        BeanUtils.copyProperties(sysDept, sysDeptTreeListVo);
                        return sysDeptTreeListVo;
                    })
                    .collect(Collectors.toList());
        }

        // 2.整理数据
        Long topId = depts.stream().map(SysDeptTreeListVo::getParentId).min(Long::compareTo).get();
        List<SysDeptTreeListVo> sysDeptTreeListVos = buildDeptListTree(depts, topId);
        return CollStreamUtil.toList(sysDeptTreeListVos, sysDeptTreeListVo -> {
            SysDeptTreeVo sysDeptTreeVo = new SysDeptTreeVo();
            BeanUtils.copyProperties(sysDeptTreeListVo, sysDeptTreeVo);
            return sysDeptTreeVo;
        });
    }

    @Override
    public SysDeptDetailVo selectDeptById(Long deptId) {
        SysDept byId = this.getById(deptId);
        SysDeptDetailVo sysDeptDetailVo = new SysDeptDetailVo();
        BeanUtils.copyProperties(byId, sysDeptDetailVo);
        return sysDeptDetailVo;
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    public boolean checkDeptExistUser(Long deptId) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>();
        queryWrapper.eq("dept_id", deptId);
        int result = userMapper.selectCount(queryWrapper);
        return result > 0 ? true : false;
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param dept 部门信息
     * @return 结果
     */
    public boolean checkDeptNameUnique(SysDept dept) {
        boolean result = true;
        //增加或者修改
        Long deptId = ObjectUtil.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
        //部门名称
        String deptName = dept.getDeptName();
        // 1.根据角色名称查询数据库是否存在此名称
        LambdaQueryWrapper<SysDept> q = new LambdaQueryWrapper<>();
        q.eq(SysDept::getDeptName, deptName).eq(SysDept::getParentId, dept.getParentId());
        SysDept one = this.getOne(q);
        if (ObjectUtil.isNotEmpty(one) && !one.getDeptId().equals(deptId)) {
            result = false;
        }
        return result;
    }

    /**
     * 新增保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public boolean insertDept(SysDept dept) {
        // 1.校验部门名称唯一
        Assert.isNotTrue(checkDeptNameUnique(dept), "新增部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        SysDept info = deptMapper.selectById(dept.getParentId());
        Assert.isNull(info, "父级部门不存在");
        // 2.准备数据
        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        dept.setLevel(info.getLevel() + 1);
        return this.save(dept);
    }

    /**
     * 修改保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateDept(SysDept dept) {
        // 1.校验
        Assert.isNotTrue(checkDeptNameUnique(dept), "修改部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        Assert.isTrue(dept.getParentId().equals(dept.getDeptId()), "修改部门'" + dept.getDeptName() + "'失败，上级部门不能是自己");
        // 2.更新子项目并改变层级结构
        SysDept newParentDept = deptMapper.selectById(dept.getParentId());
        SysDept oldDept = deptMapper.selectById(dept.getDeptId());
        if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            //修改部门级别和祖级列表
            dept.setAncestors(newAncestors);
            Integer level = newParentDept.getLevel() + 1;
            dept.setLevel(level);
            //修改子部门的信息
            // 3.查看该部门对应的子部门
            QueryWrapper<SysDept> queryWrapper = new QueryWrapper<SysDept>();
            queryWrapper.apply("find_in_set({0}, ancestors)", dept.getDeptId());
            List<SysDept> children = deptMapper.selectList(queryWrapper);
            // 4.替换子部门的祖级列表
            List<SysDept> childrenParam = CollStreamUtil.toList(children, sysDept -> {
                String childAncestors = newAncestors + "," + dept.getDeptId();
                Integer childLevel = level + 1;
                sysDept.setAncestors(childAncestors);
                sysDept.setLevel(childLevel);
                return sysDept;
            });
            this.updateBatchById(childrenParam);
        }
        // 3.更新项目
        boolean result = this.updateById(dept);
        return result;
    }

    /**
     * 删除部门管理信息
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public boolean deleteDeptById(Long deptId) {
        Assert.isTrue(checkDeptExistUser(deptId), "部门存在用户,不允许删除");
        //删除本部门和部门以下的子部门
        QueryWrapper<SysDept> queryWrapper = new QueryWrapper<SysDept>();
        queryWrapper.apply("find_in_set({0}, ancestors)", deptId);
        List<SysDept> children = deptMapper.selectList(queryWrapper);
        //子部门Id
        List<Long> longs = new ArrayList<>();
        if (CollUtil.isNotEmpty(children)) {
            longs = CollStreamUtil.toList(children, SysDept::getDeptId);
        }
        longs.add(deptId);
        return deptMapper.deleteBatchIds(longs) > 0 ? true : false;
    }

}
